/*
Date: Mon 21 Oct 2013



*/


#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //open
#include <unistd.h> //close 
#include <byteswap.h>


#define RVEX_CTRL_RESET  '2'
#define RVEX_CTRL_START '1'

#define RVEX_STAT_BUSY '3' // task is being executed
#define RVEX_STAT_IDLE '1' //task is not running or task has just finished
#define RVEX_STAT_DONE '0' //task finishes execution 

#define RVEX_DMEM_DIR "/dev/rvex-dmemory.0" //rvex data memory
#define RVEX_IMEM_DIR "/dev/rvex-imemory.0"  //rvex instruction memory 
//#define RVEX_CTRL_DIR "/sys/devices/virtual/rvex-core/rvex-smemory.0/rvex_core_ctl"
#define RVEX_CTRL_DIR "/sys/devices/virtual/rvex_core/rvex-smemory.0/rvex_core_ctl"   //rvex control register
#define RVEX_STATUS_DIR "/sys/devices/virtual/rvex_core/rvex-smemory.0/rvex_core_status" //rvex status register

#define DATA_SIZE 32
#define DATA_SIZE_READ 80

/*
int data_package [8]; //data buffer to send to rvex dmem
int data_package_read [8]; //data buffer to read rvex dmem
*/


char data_package [DATA_SIZE]; //data buffer to send to rvex dmem
char data_package2 [DATA_SIZE]; //data buffer to send to rvex dmem
int i_data_package3;
//char data_package_read [DATA_SIZE]; //data buffer to read rvex dmem
char data_package_read [DATA_SIZE_READ]; //data buffer to read rvex dmem
//char data_package_read2 [16]; //data buffer to read rvex dmem
//char data_package_read3 [400]; //data buffer to read rvex dmem


/* functon running on rovex*/
//int add(int a, int b);
int add(char a, char b);


//File *fp;

int main(int argc, char** argv ) 
{
//	char mb_parameters []= {1,2,3,4,5,6,7};
	//int r=84; 
 	//int d=85;
	char r=84;
	char d=85;
	 
	int results;
//	char results; 

	int i; 
	int num_buf_elements;
	

	
	printf("\n\nRunning MicroBlaze App\n "); 
	
	
	//num_buf_elements = sizeof(data_package)/sizeof(int); 
	num_buf_elements = sizeof(data_package)/sizeof(char); 
	
	
	/*initialize arrays */
	for(i=0; i<num_buf_elements; i++) 
	{
		data_package[i]=0;
		data_package2[i]=0;
	}


	for(i=0; i<DATA_SIZE_READ; i++)
	{
		data_package_read[i]=0;
	}
	/* start rovex communication */
	printf("Kernel call....\n "); 
	results=add(r,d);	 
	printf("Kernel call end\n "); 


 	/* validate input and output  */
	printf("\n-------------------------------------------------------------\n  " );
	printf("\nValidate results\n  " );

	printf("\nBuffer to rvex :\n  " );
	printf("\n\n  " );
	for(i=0; i<num_buf_elements; i++)
		printf("data_package[%d] => dec:%d \t  hex:%x \n ",i ,data_package[i],data_package[i] );


	printf("\nBufffer 2 to rvex :\n  " );
	printf("\n\n  " );
	for(i=0; i<num_buf_elements; i++)
		printf("data_package2[%d] => dec:%d \t  hex:%x \n ",i ,data_package2[i],data_package2[i] );



	printf("\n\n  " );
	printf("\nBuffer  from rvex :\n  " );
	//for(i=0; i<num_buf_elements; i++)
	for(i=0; i<DATA_SIZE_READ; i++)
		printf("data_package_read[%d] => dec:%d \t  hex:%x \t  \n ",i ,data_package_read[i],data_package_read[i]  );

	
	printf("Program Done\n "); 

	return 0;

}//end main function








//int add(int a, int b) 
int add(char a, char b) 
{
 	/* File discriptors of the hardware for the system calls */ 
  	int fd_rv_ctrl_reg = open(RVEX_CTRL_DIR,O_WRONLY);  	// open the control register for write only
 	// int fd_rv_status_reg = open(RVEX_CTRL_DIR,O_RDONLY); // open the status  register for read only 
  	int fd_rv_status_reg = open(RVEX_STATUS_DIR,O_RDONLY); 	// open the status  register for read only 
 	int fd_rv_dmem_reg = open(RVEX_DMEM_DIR,O_RDWR);  	// open the data memory for read and write
  
  	int check_stat; //checks system calls 
  	char command; //commands to echo to the rovex control register  
 	// int timer=0; //timeout for reading rvex datamemory
  	int i;
   	int data_size; 		//size in bytes of data to send to rovex
   	int data_type_size; 	//size of data type of the data to send to rovex 
   	int data_num_elements; 	//number of elements in data package to rovex
  
	off_t fd_current_position;  //get position of file discriptor
	int offset_bytes; //ofset for filediscriptor in bytes
	int return_value; //value to return in function call, for x264


	//int char_count; //monitor when char reaches max count, 256
	char counter=0;
	char rv_ready;
	char mb_ready;		



  	/* fill buffer to send */ 
  	
	data_size=sizeof(data_package); 
  	//data_type_size=sizeof(int);  
  	data_type_size=sizeof(char);  
  	data_num_elements= data_size/data_type_size; 
  
   	//data_package [0]=a; 
   	//data_package [1]=b; 
  
   	printf("\nData Size : %d\n ",data_size );
   	printf("Data Type Size : %d\n ",data_type_size );
   	printf("num elements : %d\n ",data_num_elements);

  	//for(i=2; i<data_num_elements; i++ ) //fill the rest of the 150 elements
  	for(i=0; i<data_num_elements; i++ ) //fill the rest of the 150 elements
  	{
	    if( (i==100) || (i==200) || (i==300) || ( i==400) ) //resent count 
		 counter=0;  
  
	     //data_package[i]=counter++ + 5;
	     data_package[i]=23;
	     data_package2[i]=34;
	}

  
   	/* validate data to send */ 
  	printf("\n\n");
  	
	/* show file discriptors id */
  	printf("fd_rv_ctrl_reg:%d\n ", fd_rv_ctrl_reg); 
  	printf("fd_rv_status_reg :%d\n ", fd_rv_status_reg); 
  	printf("fd_rv_dmem_reg:%d\n ", fd_rv_dmem_reg); 
  
	
//------------------------------------------------------------

//for(i=0; i<2; i++)
//{
	/*send 32 bytes pixel1*/  //0x120 - 0x13F


	/*send 32 bytes pixel2*/ //0x140- 0x15F 

	/*start rovex */


	/*wait for results */


	/* fetch results*/

//}

//-----------------------------------------------------------
	

//-------------------------------------------------------------------------------
//    SEND BUFFER 1 TO DMEM  //0x120 - 0x13F
//-------------------------------------------------------------------------------

	/* set cursor at correct dmem location using fd  */
	
	offset_bytes=0;
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_SET); //set cursor offset_byte further from file beginning   //address at 0x120 in Dmem
	printf("\nset cursor at offset. position now: %ld \n", fd_current_position ); 
  	

	/* send parameters to rvex */

	/* send 8 bytes of data to Dmem at position 288 byte offset. end position is 288 + 8 =296 bytes offset from beginning of file */
  	printf("\nRvex Dmem write ...\n");

	printf("Buffer 1\n");	
	printf("Writing %ld bytes \n ", sizeof(data_package));  
  	check_stat= write(fd_rv_dmem_reg,data_package,data_size); //write to 
  
  	
	if(check_stat == -1)
  	{ 
   		printf("Dmem Write Failed\n");
   		exit(0);  
  	}    
  	else  printf("Write Success\n");


 
	/* read current cursor. should be at 296 bytes */
	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_CUR); //find curent cursor
	printf("\ncurrent position in file after write: %ld \n", fd_current_position ); 
	




//-------------------------------------------------------------------------------
//    SEND BUFFER 2 TO DMEM //0x140- 0x15F
//-------------------------------------------------------------------------------
	//cursor should be now at 0x140 automatically

	/*reset cursor  */
/*	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_SET); //0x120
	printf("Reset cursor after handshaking..  current position: %ld \n", fd_current_position ); 
*/


	printf("Writing %ld bytes \n ", sizeof(data_package2));  
  	check_stat= write(fd_rv_dmem_reg,data_package2,sizeof(data_package2)); //write to 
	printf("current position in file before write: %ld \n", fd_current_position ); 


	if(check_stat == -1)
  	{ 
   		printf("Dmem Write 2 Failed\n");
   		exit(0);  
  	}    
  	else  printf("Write Success 2\n");

	/* read current cursor. should be at 296 bytes */
	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_CUR); //find curent cursor
	printf("current position in file after write 2: %ld \n", fd_current_position ); 


	/* read current cursor. should be at 296 bytes */
/*	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_status_reg ,offset_bytes,SEEK_CUR); //find curent cursor
	printf("current position of status register: %ld \n", fd_current_position ); 
*/






//-------------------------------------------------------------------------------
//    START ROVEX 
//-------------------------------------------------------------------------------
  	/* reset rvex */
  	command='2';
  	printf("\n\nrvex reset...\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);

 	if(check_stat == -1)
  	{ 
   		printf("Reset Failed\n");
   		exit(0);  
  	}    
  	else printf("Reset Success\n");

  	/* start rvex */
  	command='1';
  	//write(fd_rv_ctrl_reg,&command,sizeof(command));
  	printf("\n\nStart rvex\n"); 
  	check_stat= write(fd_rv_ctrl_reg,&command,1);   
 
  	if(check_stat == -1)
  	{ 
   		printf("Start Failed\n");
   		exit(0);  
  	}    
  	else  printf("Start Success\n\n");


//-------------------------------------------------------------------------------
//   HANDSHAKING
//-------------------------------------------------------------------------------
//		/*wait until rovex process the data */
	//printf("\nStarting handshaking\n "); 
	
	/*reset cursor */
/*	offset_bytes=16;//0x130	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_SET); 
	printf("Reset cursor for handshaking..  current position: %ld \n", fd_current_position ); 

	rv_ready=0;
  	printf("Wait for handshaking.....\n"); 
	//temp	
	check_stat= read(fd_rv_dmem_reg, &rv_ready,1); //read until rovex finishes catch the data
	printf("value at position 0x130 :%d\n ",rv_ready);  

 	while(rv_ready != 44){ //read at 0x130 
   	
		offset_bytes=16;	
		fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_SET); //0x120

		check_stat= read(fd_rv_dmem_reg, &rv_ready,1); //read until rovex finishes catch the data
	} 
  	printf("finish handshaking\n"); 

*/	



//-------------------------------------------------------------------------------
//   HANDSHAKING  -- notify rovex to fetch new data
//-------------------------------------------------------------------------------
	/*notify rovex to fetch new data */

	/*notify rovex  */
/*	mb_ready=33;
	offset_bytes=24;//0x131	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_SET); 
	printf("Reset cursor for notifying rovex..  current position: %ld \n", fd_current_position ); 
	
	check_stat= write(fd_rv_dmem_reg, &mb_ready,1); //read until rovex finishes catch the data
*/


//-------------------------------------------------------------------------------
//    Wait until rovex finish 
//-------------------------------------------------------------------------------

  	/* wait until rvex finish */
  	command='0';
  	printf("Wait until rvex finish .....\n"); 
  	while(command != '3'){ 
		/*check if rovex is finish */
   		check_stat= read(fd_rv_status_reg,&command,1); //read status until rvex control bit is 0b011=>done
	} 
  	printf("rvex done\n"); 

	/* read current cursor. should be at 296 bytes */
	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_status_reg ,offset_bytes,SEEK_CUR); //find curent cursor
	printf("current position of status register after while loop: %ld \n", fd_current_position ); 
	

//-------------------------------------------------------------------------------
//    Read Results in Dmem 
//-------------------------------------------------------------------------------
	
	
	/* Read 80 bytes from start from Data memory */
	/*reset cursor */
	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_CUR); //find curent cursor
	printf("\ncurrent position in file before reading %ld \n", fd_current_position ); 
 
	printf("reading %ld bytes \n ", sizeof(data_package_read));  
	//data_size = sizeof(data_package_read)/sizeof(char);
	
	lseek(fd_rv_dmem_reg,0, SEEK_SET); //set cursor at beginning.
	printf("\n new current position in file after cursor change %ld \n", fd_current_position ); 
	//check_stat= read(fd_rv_dmem_reg, data_package_read,data_size); 
	check_stat= read(fd_rv_dmem_reg, data_package_read,sizeof(data_package_read)); 



	/*read kernel result, int value */	
	//offset_bytes=28;//0x13C	
	offset_bytes=0;//0x120	
	lseek(fd_rv_dmem_reg,offset_bytes, SEEK_SET); //set cursor at beginning.
	printf("\n new current position in file after cursor change %ld \n", fd_current_position ); 
	check_stat= read(fd_rv_dmem_reg, &i_data_package3,4); 


  
	if(check_stat == -1)
  	{ 
   		printf("Read Failed\n");
   		exit(0);  
  	}    
  	else  printf("Read Success\n");

	printf("Read integer value,byteswap :%d\n ", bswap_32(i_data_package3) ); 

	return_value=bswap_32(i_data_package3); 
	printf("Read integer value:%d\n ", return_value ); 


	/* read current cursor */
	offset_bytes=0;	
	fd_current_position= lseek (fd_rv_dmem_reg,offset_bytes,SEEK_CUR); //find curent cursor
	printf("\ncurrent position in file after reading %ld \n", fd_current_position ); 



	



  	printf("Rvex done\n"); 


/*reset to start new data */


















	/*close the file discriptors */
  	close(fd_rv_ctrl_reg); 
  	close(fd_rv_status_reg); 
 	close(fd_rv_dmem_reg);
 //	close(fd_rv_dmem_reg2);
 //	close(fd_rv_dmem_reg3);



	return (0);

}

